//
//  ViewController.m
//  MemoryTest
//
//  Created by YaoZhaofeng on 16/6/8.
//  Copyright © 2016年 YaoZhaofeng. All rights reserved.
//

#import "ViewController.h"
#import <objc/runtime.h>
#import "XYChild.h"
#import "BlockTest.h"

static const int kIterationCount = 10000000;
const int a = 0;
@interface ViewController ()
@property (nonatomic, assign) BOOL isAuto;
@property (nonatomic, copy) NSMutableArray *mutableArray;
@property (nonatomic, assign) UIViewController *vc;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _isAuto = YES;
    
//    [self memoryTestWithAuto:_isAuto];
    
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    btn.titleLabel.text = @"click me";
    btn.backgroundColor = [UIColor redColor];
    [btn addTarget:self action:@selector(clickMe) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
    [self demo1];
}

#pragma mark - __autoreleasing
/*
 *1. __unsafe_unretained:和__weak 一样，唯一的区别便是，对象即使被销毁，指针也不会自动置空， 此时指针指向的是一个无用的野地址。如果使用此指针，程序会抛出 BAD_ACCESS 的异常。
 *
 */

- (void)demo1 {
    id __unsafe_unretained obj1 = nil;
    {
        id obj0 = [NSMutableArray array];
        [obj0 addObject:@"obj"];
        obj1 = obj0;
        NSLog(@"obj0 = %@", obj0);
    }
    NSLog(@"obj1 = %@", obj1);
}

- (void)demo2 {
    id __unsafe_unretained obj1 = nil;
    {
        id  obj0 = [[NSMutableArray alloc] init];
        [obj0 addObject:@"obj"];
        obj1 = obj0;
        NSLog(@"obj0 = %@", obj0);
    }
    NSLog(@"obj1 = %@", obj1);
}



#pragma mark - memory test

//- (void)structTest {
//    struct A
//    {
//        int   a;
//        char  b;
//        double c;
//        char  d;
//    };
//
//    struct B
//    {
//        char  a;
//        double b;
//        char  c;
//    };
//    
//    printf("int =%lu,char=%lu,double=%lu\n",sizeof(int),sizeof(char),sizeof(double));
//    printf("structA=%lu  structB=%lu\n",sizeof(struct A),sizeof(struct B));
//}

- (void)tempTest {
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@1,@2, nil];
    array = [[NSMutableArray alloc] initWithObjects:@1,@2,@3, nil];
    NSLog(@"array is ... %@", NSStringFromClass([array class]));
    if ([array isMemberOfClass:[NSArray class]]) {
        NSLog(@"array is NSArray");
    } else if ([array isMemberOfClass:[NSMutableArray class]]) {
        NSLog(@"array is NSMutableArray");
    }
    _mutableArray = array;
    if ([_mutableArray isMemberOfClass:[NSArray class]]) {
        NSLog(@"_mutableArray is NSArray");
    } else if ([_mutableArray isMemberOfClass:[NSMutableArray class]]) {
        NSLog(@"_mutableArray is NSMutableArray");
    }

    if ([self.mutableArray isMemberOfClass:[NSArray class]]) {
        NSLog(@"self.mutableArray is NSArray");
    } else if ([self.mutableArray isMemberOfClass:[NSMutableArray class]]) {
        NSLog(@"self.mutableArray is NSMutableArray");
    }
    [self.mutableArray removeObjectAtIndex:0];
    NSLog(@"%@", self.mutableArray);
    self.vc = [[UIViewController alloc] init];
    [self blockTest];
    
    extern int globalInt;
    NSLog(@"before::%d", globalInt++);
    NSLog(@"after::%d", globalInt);
//    const int a = 0;
    NSLog(@"a...address::%p", &a);
    int *p = &a;
    NSLog(@"before...p::%p , a::%p", p, &a);
    *p = 1;
    NSLog(@"after...p::%p , a::%p", p, &a);
    NSLog(@"p....%d , a.....%d", *p, a);
}

/**
 --堆地址要小于栈地址，又因为iOS中一个进程的栈区内存只有1M，Mac也只有8M--
 
 Block不允许修改外部变量的值，所谓外部变量的值，指的是栈中指针的内存地址。
 __block所启的作用，就是观察到该变量被block内部持有的时候，将其地址从栈中放入到堆中。从而使得block内部也可以修改变量的值。
 */
- (void)blockTest {
    __block int a = 0;
    NSLog(@"定义前：%p", &a);         //栈区
    void (^foo)(void) = ^{
        a = 1;
        NSLog(@"block内部：%p", &a);    //堆区
    };
    NSLog(@"定义后：%p", &a);         //堆区
    foo();
    
    
//    NSMutableString *a = [NSMutableString stringWithString:@"Tom"];
//    NSLog(@"\n 定以前：------------------------------------\n\
//          a指向的堆中地址：%p；a在栈中的指针地址：%p", a, &a);               //a在栈区
//    void (^foo)(void) = ^{
//        a.string = @"Jerry";
//        NSLog(@"\n block内部：------------------------------------\n\
//              a指向的堆中地址：%p；a在栈中的指针地址：%p", a, &a);               //a在栈区
////        a = [NSMutableString stringWithString:@"William"];
//    };
//    foo();
//    NSLog(@"\n 定以后：------------------------------------\n\
//          a指向的堆中地址：%p；a在栈中的指针地址：%p", a, &a);               //a在栈区
}

- (void)constTest:(BOOL)result {
    const BOOL test = result;
    NSLog(@"test is %i", test);
    
}

- (void)deallocTest {
//    XYChild *child = [[XYChild alloc] init];
//    child = nil;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)clickMe {
    NSLog(@"vc::%@",self.vc);
    return;
    _isAuto = !_isAuto;
    if (_isAuto) {
        NSLog(@"利用autoreleasepool");
    }
    [self memoryTestWithAuto:_isAuto];
    if (_isAuto) {
        NSLog(@"利用autoreleasepool");
    }
}

- (void)memoryTestWithAuto:(BOOL)isAuto{
//    __weak NSString *myStr;
//    for (int i = 0; i < kIterationCount; i++) {
//        if (isAuto) {
//            @autoreleasepool {
//                NSString *str = [NSString stringWithFormat:@"132"];
////                NSString *str = [[NSString alloc] initWithFormat:@"i is %d",i];
////                NSLog(@"str is %@",str);
//                
//            }
//        }
//        else{
//            NSString *str = [NSString stringWithFormat:@"132"];
////            NSString *str = [[NSString alloc] initWithFormat:@"i is %d",i];
////            NSLog(@"str is %@",str);
//        }
//    }
//    NSLog(@"myStr is %@",myStr);
}

@end
